﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Web;
using ChatApp.Core.Facade;
using ChatApp.Core.Info;
using Microsoft.AspNet.SignalR;
using ChatApp.Common;

namespace ChatApp.Hubs
{
    public class ChatHub : Hub
    {
        #region Data Members

        private static List<UserDetail> ConnectedUsers = new List<UserDetail>();
        static List<MessageDetail> CurrentMessage = new List<MessageDetail>();
        static IList<UserInfo> lUserInfo;
        static IList<MessageInfo> lMessageInfo;
        private IUserFacade aUserFacade = new UserFacade();
        private IMessageFacade aMessageFacade = new MessageFacade();

        #endregion

        #region Methods

        public void Connect(string userName)
        {
            var id = Context.ConnectionId;
            var isConnected = false;
            var lUserInfo = aUserFacade.GetUserSystemManager("system");

            if (ConnectedUsers.Count == 0)
            {
                foreach (var aUserInfo in lUserInfo)
                {
                    ConnectedUsers.Add(new UserDetail()
                    {
                        ConnectionId = aUserInfo.UserName,
                        UserName = aUserInfo.UserName,
                        isConnect = false,
                        Role = "system"
                    });
                    // send to all except caller client
                    Clients.AllExcept(id).onNewUserConnected(true, userName);
                }
            }
            if (ConnectedUsers.Count(x => x.UserName.Trim() == userName.Trim()) != 0)
            {
                var aUserDetail = ConnectedUsers.FirstOrDefault(x => x.UserName.Trim() == userName.Trim());
                if (aUserDetail.Role == "system")
                {
                    aUserDetail.isConnect = true;
                    // send to all except caller client
                    Clients.AllExcept(id).onUpdateStatuss(id, userName);
                }
            }
            if (ConnectedUsers.Count(x => x.UserName.Trim() == userName.Trim()) == 0)
            {
                ConnectedUsers.Add(new UserDetail {ConnectionId = id, UserName = userName, isConnect = true});

                // send to all except caller client
                Clients.AllExcept(id).onNewUserConnected(id, userName);
            }
            // send to caller
            Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage);
        }

        //public void SendMessageToAll(string userName, string message)
        //{
        //    // store last 100 messages in cache
        //    AddMessageinCache(userName, message);

        //    // Broad cast message
        //    Clients.All.messageReceived(userName, message);
        //}

        public void SetReadPrivateMessage(string toUserId)
        {
            string fromUserId = ConnectedUsers.FirstOrDefault(x => x.UserName.Equals(Context.User.Identity.Name)).ConnectionId;

            var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
            var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);

            if (toUser != null && fromUser != null)
            {
                aMessageFacade.UpdateMessage(toUser.UserName, fromUser.UserName);
            }
        }

        public void SendPrivateMessage(string toUserId, string message)
        {

            string fromUserId = ConnectedUsers.FirstOrDefault(x=>x.UserName.Equals(Context.User.Identity.Name)).ConnectionId;

            var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
            var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);


            if (toUser != null && fromUser != null)
            {
                // send to 
                Clients.Client(toUserId).sendPrivateMessage(fromUserId, fromUser.UserName, message);

                // send to caller user
                Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message);

                // insert to database
                var aUserInfoFrom = aUserFacade.getUser(fromUser.UserName);
                var aUserInfoTo = aUserFacade.getUser(toUser.UserName);
                var aMessageInfo = new MessageInfo();
                aMessageInfo.UserIdFrom = aUserInfoFrom.UserId;
                aMessageInfo.UserIdTo = aUserInfoTo.UserId;
                aMessageInfo.is_read = false;
                aMessageInfo.Massage = message;
                aMessageInfo.TimeSend = DateTime.Now;

                aMessageFacade.InsertMessage(aMessageInfo);
            }

        }

        public override System.Threading.Tasks.Task OnDisconnected()
        {
            
            var item = ConnectedUsers.FirstOrDefault(x => x.UserName.Equals(Context.User.Identity.Name));
            if (item != null)
            {

                if (item.Role == "system")
                {
                    if (ConnectedUsers.Count(x => x.UserName.Equals(Context.User.Identity.Name)) == 0)
                    {
                        item.isConnect = false;
                        ConnectedUsers.Add(item);
                        Clients.AllExcept(item.ConnectionId).onUpdateStatuss(item.isConnect, item.UserName);
                    }
                    else
                    {
                        item.isConnect = false;
                        Clients.AllExcept(item.ConnectionId).onUpdateStatuss(item.isConnect, item.UserName);
                    }
                }
                else
                {
                    ConnectedUsers.Remove(item);
                    var id = item.ConnectionId;
                    Clients.All.onUserDisconnected(id, item.UserName);
                }
            }

            return base.OnDisconnected();
        }


        #endregion

        #region private Messages

        private void AddMessageinCache(string userName, string message)
        {
            CurrentMessage.Add(new MessageDetail { UserName = userName, Message = message });

            if (CurrentMessage.Count > 100)
                CurrentMessage.RemoveAt(0);
        }

        #endregion
    }

}